package com.wang.transfer.util.io;

import com.wang.common.common.AService;
import com.wang.common.common.ErrorCode;
import com.wang.common.exception.BusinessException;
import com.wang.common.utils.StreamUtil;
import com.wang.common.utils.Utils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.TextPosition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 不同文件流
 */
@Component
public class DifferentFileBuffered extends AService {

    private static final Logger logger = LoggerFactory.getLogger(DifferentFileBuffered.class);

    private static final String separator1 = "\\\\";
    private static final String separator2 = "/";
    private static final String regex = ",";
    private static final String LFM = "lfm/";

    /**
     * 设置Content-Type
     * Content-Disposition: inline 页面解析；attachment 下载到本地
     */
    public static class ContentType {
        public static final String HTML = "text/html";
        public static final String TXT = "text/plain";
        public static final String XML = "text/xml";
        public static final String GIF = "image/gif";
        public static final String JPEG = "image/jpeg";
        public static final String PNG = "image/png";
        public static final String AXML = "application/xml";
        public static final String JSON = "application/json";
        public static final String PDF = "application/pdf";
        public static final String WORD = "application/msword";
        public static final String OCTET = "application/octet-stream";
        public static final String MSDOWNLOAD = "application/x-msdownload";
    }

    /**
     * 设置图片类型imageType
     */
    public enum ImageType {
        PNG("PNG", ContentType.OCTET),
        JPEG("JPEG", ContentType.OCTET),
        GIF("GIF", ContentType.OCTET);

        private final String type;
        private final String content;

        ImageType(String type, String content) {
            this.type = type;
            this.content = content;
        }

        public static ImageType getImageType(String type) {
            if (type.toLowerCase(Locale.ROOT).equals(PNG.type.toLowerCase(Locale.ROOT))) {
                return PNG;
            } else if (type.toLowerCase(Locale.ROOT).equals(JPEG.type.toLowerCase(Locale.ROOT))) {
                return JPEG;
            } else {
                return GIF;
            }
        }
    }

    /**
     * 获取文件流
     *
     * @param filepath    文件路径
     * @param contentType Content-Type
     */
    public void getFileStream(String filepath, String contentType) throws IOException {
        logger.info("===================getFileStream[filepath = " + filepath + ", contentType = " + contentType + "]");
        HttpServletResponse response = res;
        byte[] bytes = new byte[1024]; //缓冲数组
        int i;
        FileInputStream fileInputStream = null;
        BufferedInputStream bufferedInputStream = null;
        OutputStream outputStream = response.getOutputStream();

        File file = new File(filepath);
        if (!file.exists()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件不存在");
        }
        String filename = this.getFilename(filepath);
        response.reset();
        response.setContentType(contentType);
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
        try {
            fileInputStream = new FileInputStream(file);
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            while ((i = bufferedInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, i);
            }
            outputStream.flush();
        } catch (Exception e) {
            logger.error("文件下载失败:" + e);
        } finally {
            StreamUtil.closeInputStream(fileInputStream, bufferedInputStream);
            StreamUtil.closeOutputStream(outputStream);
        }
    }

    /**
     * pdf获取图片流
     *
     * @param path      pdf路径
     * @param imageType 图片类型
     */
    public void getImageStream(String path, String imageType) throws IOException {
        logger.info("===================getImageStream[path = " + path + ", imageType = " + imageType + "]");
        HttpServletResponse response = res;
        ImageType IType = ImageType.getImageType(imageType);
        byte[] bytes = new byte[1024];
        int i;
        ByteArrayInputStream byteArrayInputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        BufferedInputStream bufferedInputStream = null;
        BufferedImage bufferedImage;
        OutputStream outputStream = response.getOutputStream();

        File file = new File(path);
        if (!file.exists()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "pdf不存在");
        }
        String filename = this.getFilename(path);
        response.reset();
        response.setContentType(IType.content);
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
        try {
            bufferedImage = new BufferedImage(650, 1050, BufferedImage.TYPE_INT_RGB);
            //  mstmc.ttf无法读取
//            PDDocument document = PDDocument.load(file);
//            PDFRenderer pdfRenderer = new PDFRenderer(document);
//            bufferedImage = pdfRenderer.renderImage(0, 1.8f);
            byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, IType.type, byteArrayOutputStream);
            byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            bufferedInputStream = new BufferedInputStream(byteArrayInputStream);
            while ((i = bufferedInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, i);
            }
            outputStream.flush();
        } catch (Exception e) {
            logger.error("图片下载失败：" + e);
        } finally {
            StreamUtil.closeInputStream(byteArrayInputStream, bufferedInputStream);
            StreamUtil.closeOutputStream(outputStream, byteArrayOutputStream);
        }
    }

    /**
     * 获取zip文件流
     *
     * @param path 文件路径，分隔符 <strong>,</strong>
     */
    public void getZipStream(String path) throws IOException {
        String[] paths = path.split(regex);
        if (Utils.isEmpty(paths)) throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件路径为空");
        logger.info("====================files path:");
        for (String s : paths) logger.info(s);
        HttpServletResponse response = res;
        ServletOutputStream outputStream = response.getOutputStream();
        ZipOutputStream zipOutputStream = null;
        FileInputStream fileInputStream = null;
        String LFName = "DP_" + new Date().getTime() + String.valueOf(Math.random()).substring(0, 5) + ".zip";
        String filename = new String(LFName.getBytes(), StandardCharsets.ISO_8859_1);
        response.setHeader("Content-Disposition", "attachment;filename=" + filename);
        String LFPath = LFM + LFName;
        File file = new File(LFM);
        if (!file.exists() && !file.isDirectory()) {
            boolean mkdir = file.mkdir();
            if (!mkdir) logger.error("目录" + LFM + "创建失败");
        }
        try {
            zipOutputStream = new ZipOutputStream(new FileOutputStream(LFPath));
            for (String s : paths) {
                this.fileToZip(s, zipOutputStream);
            }
            zipOutputStream.flush();
        } catch (IOException e) {
            StreamUtil.closeOutputStream(outputStream);
            StreamUtil.deleteLFile(LFPath);
            logger.error("zip文件" + LFName + "创建失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "zip文件" + LFName + "创建失败");
        } finally {
            StreamUtil.closeOutputStream(zipOutputStream);
        }
        try {
            fileInputStream = new FileInputStream(LFPath);
            IOUtils.copy(fileInputStream, outputStream);
            outputStream.flush();
        } catch (IOException e) {
            logger.error("zip文件" + LFName + "下载失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "zip文件" + LFName + "下载失败");
        } finally {
            StreamUtil.closeOutputStream(outputStream);
            StreamUtil.closeInputStream(fileInputStream);
            StreamUtil.deleteLFile(LFPath);
        }

    }

    /**
     * 获取文件名
     *
     * @param filepath 文件路径
     * @return 文件名
     */
    private String getFilename(String filepath) {
        // 解决分隔符不同系统问题
        String filename = filepath.split(separator1)[filepath.split(separator1).length - 1];
        if (filepath.equals(filename)) {
            filename = filepath.split(separator2)[filepath.split(separator2).length - 1];
        }
        logger.info("====================filename: " + filename);
        return filename;
    }

    /**
     * 将文件加载到zip输出流中
     *
     * @param filepath        文件地址
     * @param zipOutputStream zip输出流
     */
    private void fileToZip(String filepath, ZipOutputStream zipOutputStream) throws IOException {
        filepath = filepath.replaceAll("\\+", "%20");
        byte[] bytes = new byte[1024 * 10];
        InputStream fileInput = null;
        BufferedInputStream bufferedInputStream = null;
        File file = new File(filepath);
        String filename = FilenameUtils.getBaseName(URLDecoder.decode(file.getName(), "UTF-8")) + "-"
                + new Date().getTime() + "." + FilenameUtils.getExtension(file.getName());
//        InputStream fileInput = this.getInputStream(filepath);
        try {
            fileInput = new FileInputStream(file);
            bufferedInputStream = new BufferedInputStream(fileInput);
            zipOutputStream.putNextEntry(new ZipEntry(filename));
            int length;
            while ((length = bufferedInputStream.read(bytes, 0, 1024 * 10)) != -1) {
                zipOutputStream.write(bytes, 0, length);
            }
        } catch (IOException e) {
            logger.error("文件" + filename + "加载失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "文件" + filename + "加载失败");
        } finally {
            StreamUtil.closeInputStream(fileInput, bufferedInputStream);
        }
        try (InputStream inputStream = new FileInputStream(file); BufferedInputStream bufferedInputStream1 = new BufferedInputStream(inputStream)) {
            zipOutputStream.putNextEntry(new ZipEntry(filename));
            int length;
            while ((length = bufferedInputStream1.read(bytes, 0, 1024 * 10)) != -1) {
                zipOutputStream.write(bytes, 0, length);
            }
        } catch (IOException e) {
            logger.error("文件" + filename + "加载失败", e);
        }
    }

    /**
     * 发送http请求获取流
     *
     * @param httpUrl 网络地址
     * @return inputStream
     */
    private InputStream getInputStream(String httpUrl) throws IOException {
        InputStream inputStream = null;
        URL url = new URL(httpUrl);
        URLConnection urlConnection = url.openConnection();
        urlConnection.connect();
        HttpURLConnection httpCon = (HttpURLConnection) urlConnection;
        int responseCode = httpCon.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            inputStream = urlConnection.getInputStream();
        }
        return inputStream;
    }

    /**
     * 合拼多个pdf文件
     */
    private static final String pdf1 = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\3.pdf";
    private static final String pdf2 = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\4.pdf";
    private static final String pdf3 = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\dd.pdf";
    public void hBPdf() throws IOException {
        File file1 = new File(pdf1);
        File file2 = new File(pdf2);
        PDDocument[] pdDocuments = new PDDocument[2];
        PDDocument doc1 = PDDocument.load(file1);
        PDDocument doc2 = PDDocument.load(file2);
        pdDocuments[0] = doc1;
        pdDocuments[1] = doc2;
        PDFMergerUtility PDFMerger = new PDFMergerUtility();
//        PDFMerger.setDestinationFileName(pdf3);
        PDFMerger.addSource(file1);
        PDFMerger.addSource(file2);
        PDDocument document = new PDDocument();
        PDFMerger.appendDocument(document, pdDocuments[0]);
        PDFMerger.appendDocument(document, pdDocuments[1]);
        document.save(pdf3);
        doc1.close();
        doc2.close();

//        PDFMerger.addSource(file1);
//        if (file2.exists() && file2.isFile()) {
//            PDFMerger.addSource(file2);
//        } else {
//            System.out.println("file2 not found!");
//        }
//        PDFMerger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
    }

    public void pdfToImage() {
        byte[] buffer = new byte[1024];//建立缓冲数组
        BufferedInputStream bufferedInputStream = null;
        OutputStream outputStream = null;
        BufferedImage image = null;
        String LFPath = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\dd.pdf";
        try {
            File file = new File(LFPath);
            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
//            doc.save("D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\ff.pdf");
//            doc.close();
            int totalPage = doc.getNumberOfPages();//获取页数量
            logger.info(">>>>>>>>>>pdf的页数为 : "+totalPage+ " 页.");
            if(totalPage >= 1){
                BufferedImage temp = null;
                BufferedImage combined = null;
                for(int i = 0; i < totalPage; i++){
//                    image = renderer.renderImage(i, 1.32f);
                    image = renderer.renderImageWithDPI(i, 100);
                    if (i > 0){
                        combined = new BufferedImage(image.getWidth(), image.getHeight() + temp.getHeight(), BufferedImage.TYPE_INT_RGB);
                        // paint both images, preserving the alpha channels
                        Graphics g = combined.getGraphics();
                        g.drawImage(temp, 0, 0, null);
                        g.drawImage(image, 0, temp.getHeight(), null);
                        // 释放此图形的上下文以及它使用的所有系统资源。
                        temp = combined;
                        g.dispose();
                    }else{
                        temp = image;
                    }
                }
                image = temp;
            }
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(image, "png", os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            bufferedInputStream = new BufferedInputStream(is);
            outputStream = new FileOutputStream("D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\dd.png");
            int i = bufferedInputStream.read(buffer);
            while (i != -1) {
                outputStream.write(buffer, 0, i);
                i = bufferedInputStream.read(buffer);
            }
            outputStream.flush();
            outputStream.close();
            doc.close();
            logger.info("******** 图片输出完成 ******** ");
        } catch (IOException e) {
            e.printStackTrace();
            logger.info(">>>>>下载失败:" + e);
        } finally {
            if (bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                } catch (IOException e2) {
                    e2.printStackTrace();
                    logger.info(">>>>>下载失败:" + e2);
                }
            }
        }
    }

    public void yPic() throws IOException {
        String LFPath = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\dd.pdf";
        String ee = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\ee.png";
        File file = new File(LFPath);
        PDDocument doc = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(doc);
        int picNum = doc.getNumberOfPages();//获取页数量
        int height = 0, //总高度
        width = 0, //总宽度
        _height = 0; //临时的高度，或保存偏移高度
        int[] heightArray = new int[picNum]; //保存每个文件的高度
        BufferedImage buffer = null;//保存图片流
        for (int i = 0; i < picNum; i++) {
            buffer = renderer.renderImage(i, 1.8f, org.apache.pdfbox.rendering.ImageType.RGB);
            heightArray[i] = _height = buffer.getHeight();//图片高度
            if (i == 0) {
                width = buffer.getWidth();//图片宽度
            }
            height += _height;//获取总高度
        }
        // 生成新图片
        BufferedImage imageResult = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = imageResult.getGraphics();
        for (int i = 0; i < picNum; i++) {
            buffer = renderer.renderImage(i, 1.8f, org.apache.pdfbox.rendering.ImageType.RGB);
            graphics.drawImage(buffer, 0, i == 0 ? 0 : heightArray[i], null);
        }
        graphics.dispose();
        File outFile = new File(ee);
        ImageIO.write(imageResult, "jpg", outFile);//写图片
    }

    public void imgToPdf() throws IOException {
        String file = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\img.pdf";
        BufferedImage image = ImageIO.read(new File("D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\dd.png"));
        PDDocument document = new PDDocument();
        PDImageXObject imageObject = LosslessFactory.createFromImage(document, image);
        PDPage pdPage = new PDPage(PDRectangle.A4);
        document.addPage(pdPage);
        PDPageContentStream pageStream = new PDPageContentStream(document, pdPage);
        float height = pdPage.getMediaBox().getHeight();
        float y = pdPage.getMediaBox().getHeight() - height;
        pageStream.drawImage(imageObject, 0, y, pdPage.getMediaBox().getWidth(), height);
        pageStream.close();
        document.save(file);
        document.close();
    }

    public void pdfToImages() {
        byte[] buffer = new byte[1024];
        BufferedInputStream bufferedInputStream = null;
        BufferedImage image = null;
        String path = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\imgs\\";
        String LFPath = "D:\\ProjectsInfo\\IdeaProjects\\daily-platform\\lfm\\dd.pdf";
        try {
            PDDocument doc = PDDocument.load(new File(LFPath));
            PDFRenderer renderer = new PDFRenderer(doc);
            int countPage = doc.getNumberOfPages();
            for (int i = 0; i < countPage; i++) {
                image = renderer.renderImage(i, 1.8f);
                FileOutputStream iFile = new FileOutputStream(path + i + ".jpg");
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ImageIO.write(image, "jpg", os);
                InputStream is = new ByteArrayInputStream(os.toByteArray());
                bufferedInputStream = new BufferedInputStream(is);
                int n = bufferedInputStream.read(buffer);
                while (n != -1) {
                    iFile.write(buffer, 0, n);
                    n = bufferedInputStream.read(buffer);
                }
            }
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedInputStream != null) {
                    bufferedInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
//        new DifferentFileBuffered().hBPdf();
        new DifferentFileBuffered().pdfToImage();
//        new DifferentFileBuffered().yPic();
//        new DifferentFileBuffered().imgToPdf();

//        BigDecimal total = new BigDecimal("0.00");
//        total = total.add(new BigDecimal("232.33"));
//        System.out.println(total);
//        String trans = "234324,23423,23423,";
//        String[] split = trans.split(",");
//        for (String s : split) {
//            System.out.println(s);
//        }
//        new DifferentFileBuffered().pdfToImages();
    }

}
